﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

namespace CoreEx.Database.Query
{
    /// <summary>
    /// Represents a database query.
    /// </summary>
    public interface IQuery 
    {        
        /// <summary>
        /// Creates a new <see cref="ISelectQuery"/> instance.
        /// </summary>
        /// <param name="expressions">A list of expressions that defines the projection of the query.</param>
        /// <returns>A <see cref="ISelectQuery"/> instance.</returns>
        SelectQueryExpression Select(params IExpression[] expressions);
        
        /// <summary>
        /// Creates a new <see cref="ISelectQuery"/> instance.
        /// </summary>
        /// <param name="expressions">A list of functors that is used to create the expressions that defines the projection of the query.</param>        
        /// <returns></returns>
        SelectQueryExpression Select(params Func<IExpressionFactory,IExpression>[] expressions);


        IUpdateQuery Update(ITableExpression tableExpression);

        IUpdateQuery Update(Func<IExpressionFactory,IExpression> tableExpression);
       
    }


    public interface IQueryExpression<TQuery> : IQueryExpression
    {
        /// <summary>
        /// Specifies the tables, views, derived tables, and joined tables used in DELETE, SELECT, and UPDATE statements.
        /// </summary>
        /// <param name="expressions"></param>
        /// <returns></returns>
        TQuery From(params Func<IExpressionFactory, IExpression>[] expressions);

        TQuery From(params IExpression[] expressions);
        
        
        
        /// <summary>
        /// Creates an inner join against the <paramref name="target"/>.
        /// </summary>
        /// <param name="target">The target exression to join</param>
        /// <param name="expression">The experession used to join the <paramref name="target"/></param>.
        /// <returns></returns>        
        TQuery InnerJoin(IExpression target, IExpression expression);



        TQuery InnerJoin(Func<IExpressionFactory, IExpression> target, Func<IExpressionFactory, IExpression> expression);


        /// <summary>
        /// Creates a left outer join against <paramref name="target"/>.
        /// </summary>
        /// <param name="target">The target exression to join</param>
        /// <param name="expression">The experession used to join the <paramref name="target"/></param>.
        /// <returns></returns>        
        TQuery LeftOuterJoin(IExpression target, IExpression expression);

        /// <summary>
        /// Creates a right outer join against <paramref name="target"/>.
        /// </summary>
        /// <param name="target">The target exression to join</param>
        /// <param name="expression">The experession used to join the <paramref name="target"/></param>.
        /// <returns></returns>        
        TQuery RightOuterJoin(IExpression target, IExpression expression);

        /// <summary>
        /// Specifies the WHERE clause for the query.
        /// </summary>
        /// <param name="expression">An expression describing the filter constraints for the query.</param>
        /// <returns></returns>
        TQuery Where(Func<IExpressionFactory, IExpression> expression);

        TQuery Where(IExpression expression);

       
    }



    public interface ISelectQueryExpression : IQueryExpression<ISelectQueryExpression>
    {                       
        /// <summary>
        /// Spesifies the GROUP BY clause for the query.
        /// </summary>
        /// <param name="expression">A <see cref="IExpression"/> list that defines the grouping for the query.</param>
        /// <returns></returns>
        ISelectQueryExpression GroupBy(params IExpression[] expression);

        /// <summary>
        /// Spesifies the ORDER BY clause for the query.
        /// </summary>
        /// <param name="expression">A <see cref="IExpression"/> list that defines the grouping for the query.</param>
        /// <returns></returns>
        ISelectQueryExpression OrderBy(params IExpression[] expression);

        /// <summary>
        /// Spesifies the ORDER BY clause for the query
        /// </summary>
        /// <param name="expressions">A list of function delegates that is used to create <see cref="IOrderByExpression"/> instances</param>
        /// <returns></returns>
        ISelectQueryExpression OrderBy(params Func<IExpressionFactory, IOrderByExpression>[] expressions);



        ISelectQueryExpression Select(params IExpression[] expression);

        ISelectQueryExpression Select(params Func<IExpressionFactory, IExpression>[] expressions);

    }


    public interface IUpdateQuery : IQueryExpression<IUpdateQuery>
    {
        IUpdateQuery Set(IExpression target, IExpression value);
    }



}
